package com.mxbbx.wdn.domain.role;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.management.relation.RoleNotFoundException;

import com.mxbbx.wdn.database.DBUtil;
import com.mxbbx.wdn.domain.menu.Menu;

/**
 * 角色管理模块类
 * 
 * @author 
 * 
 */
public class Role {
	public Role() {

	}

	/**
	 * 角色编号
	 */
	private String roleId;
	/**
	 * 角色名称
	 */
	private String roleName;
	/**
	 * 角色对应权限列表
	 */
	private Set<Menu> menus;

	public Role(String roleId) throws RoleNotFoundException, SQLException {
		load(roleId);
	}

	public Role(String roleId, String roleName) {
		this.roleId = roleId;
		this.roleName = roleName;
	}

	public void addRole(String roleName, String[] menuIds) throws SQLException {
		Connection conn = null;
		this.roleName = roleName;
		try {
			conn = DBUtil.getConn();
			// 1：开启手动提交事务
			conn.setAutoCommit(false);
			// 2:保存角色信息到数据库
			saveToDB(conn);
			// 3:循环关联菜单信息
			if (menuIds != null) {
				for (String m : menuIds) {
					bindMenu(conn, m);
				}
			}
			// 4：提交事务
			conn.commit();
		} catch (SQLException e) {
			conn.rollback();
			throw e;
		} finally {
			DBUtil.close(conn);
		}
	}

	private void saveToDB(Connection conn) throws SQLException {
		PreparedStatement pstmt = null;
		try {
			StringBuffer sqlBuff = new StringBuffer(
					"insert into role(roleId,roleName)");
			sqlBuff.append("values(?,?)");
			pstmt = conn.prepareStatement(sqlBuff.toString());
			pstmt.setString(1, this.roleId);
			pstmt.setString(2, this.roleName);
			pstmt.executeUpdate();
		} catch (SQLException e) {
			throw new SQLException("Failed to insert into table !", e);
		} finally {
			DBUtil.close(pstmt);
		}
	}

	public void editRole(String[] menuIds) throws SQLException {
		Connection conn = null;
		try {
			conn = DBUtil.getConn();
			conn.setAutoCommit(false);
			eidtToDB(conn);
			// 删除原由角色关联
			unbindMenu(conn);
			// 循环关联菜单信息
			for (String m : menuIds) {
				bindMenu(conn, m);
			}
			conn.commit();
		} catch (SQLException e) {
			conn.rollback();
			throw e;
		} finally {
			DBUtil.close(conn);
		}
	}

	public void delRole(String roleId) throws SQLException {
		Connection conn = null;
		this.roleId = roleId;
		try {
			conn = DBUtil.getConn();
			conn.setAutoCommit(false);
			deleteFromDB(conn);
			// 删除关联菜单信息
			unbindMenu(conn);
			conn.commit();
		} catch (SQLException e) {
			conn.rollback();
			throw e;
		} finally {
			DBUtil.close(conn);
		}
	}

	private void deleteFromDB(Connection conn) throws SQLException {
		PreparedStatement pstmt = null;
		try {
			StringBuffer sqlBuff = new StringBuffer(
					"delete from role where roleId=?");
			pstmt = conn.prepareStatement(sqlBuff.toString());
			pstmt.setString(1, this.roleId);

			pstmt.executeUpdate();
		} catch (SQLException e) {
			throw new SQLException("Failed to delete record from table !", e);
		} finally {
			DBUtil.close(pstmt);
		}

	}

	private void eidtToDB(Connection conn) throws SQLException {

		PreparedStatement pstmt = null;
		try {
			StringBuffer sqlBuff = new StringBuffer(
					"update role t set t.roleName=?  where t.roleId=?");
			pstmt = conn.prepareStatement(sqlBuff.toString());
			pstmt.setString(1, this.roleName);
			pstmt.setString(2, this.roleId);
			pstmt.executeUpdate();
		} catch (SQLException e) {
			throw new SQLException("Failed to update role  !", e);
		} finally {
			DBUtil.close(pstmt);
		}
	}

	private void bindMenu(Connection conn, String menuId) throws SQLException {
		PreparedStatement pstmt = null;
		try {
			StringBuffer sqlBuff = new StringBuffer(
					"insert into role_menu(roleId,menuId)");
			sqlBuff.append("values(?,?)");
			pstmt = conn.prepareStatement(sqlBuff.toString());
			pstmt.setString(1, this.roleId);
			pstmt.setString(2, menuId);
			pstmt.executeUpdate();
		} catch (SQLException e) {
			throw new SQLException("Failed to bind to menu!", e);
		} finally {
			DBUtil.close(pstmt);
		}
	}

	private void unbindMenu(Connection conn) throws SQLException {
		PreparedStatement pstmt = null;
		try {
			StringBuffer sqlBuff = new StringBuffer(
					"delete from role_menu where roleId=?");
			pstmt = conn.prepareStatement(sqlBuff.toString());
			pstmt.setString(1, this.roleId);
			pstmt.executeUpdate();
		} catch (SQLException e) {
			throw new SQLException("Failed to unbind to menu!", e);
		} finally {
			DBUtil.close(pstmt);
		}
	}

	public void load(String roleId) throws RoleNotFoundException, SQLException {
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		try {
			conn = DBUtil.getConn();
			pstmt = conn.prepareStatement("select * from role where roleId=?");
			int index = 1;
			pstmt.setString(index, roleId);
			rs = pstmt.executeQuery();
			if (rs.next()) {
				this.roleId = rs.getString("roleId");
				this.roleName = rs.getString("roleName");
			} else {
				throw new RoleNotFoundException("Role with id " + roleId
						+ " could not be loaded from the database.");
			}

		} catch (SQLException e) {
			throw new RoleNotFoundException("Role with id " + roleId
					+ " could not be loaded from the database.");
		} finally {
			DBUtil.close(rs, pstmt, conn);
		}

	}

	public String getRoleId() {
		return roleId;
	}

	public void setRoleId(String roleId) {
		this.roleId = roleId;
	}

	public String getRoleName() {
		return roleName;
	}

	public void setRoleName(String roleName) {
		this.roleName = roleName;
	}

	private List<String> getMenuIds() {

		List<String> menuIds = new ArrayList<String>();
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		try {
			conn = DBUtil.getConn();
			pstmt = conn
					.prepareStatement("select menuId from role_menu where roleId=?");
			int index = 1;
			pstmt.setString(index++, roleId);
			rs = pstmt.executeQuery();
			while (rs.next()) {
				menuIds.add(rs.getString(1));
			}
		} catch (SQLException e) {

			e.printStackTrace();

		} finally {
			DBUtil.close(rs, pstmt, conn);
		}
		return menuIds;
	}

	public Set<Menu> getMenus() {
		try {
			if (menus == null) {
				menus = new HashSet<Menu>();
				List<String> menuIds = getMenuIds();
				for (String menuId : menuIds) {
					Menu menu = new Menu(menuId);
					menus.add(menu);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return menus;
	}

	public void setMenus(Set<Menu> menus) {
		this.menus = menus;
	}

}